<template>
  <basic-container class="cost-calculation">

    <div class="map-box">
      <section class="address-box" v-clickoutside="onSearchClickOutside">
        <div class="address-top-box">
          <CitySelect size="small" ref="citySelect" class="w-100 mb-10" v-model="cityId" clearable
            @change="handleCityChange" @loadedList="handleLoadedCityList" filterable></CitySelect>
          <div class="fr ml-10">
            <el-checkbox class="mr-10" v-model="checkOnMap" border size="small">地图选址</el-checkbox>
            <el-button type="primary" size="small" @click="handleCost">测算</el-button>
          </div>
        </div>
        <div class="mb-10">
          <el-input size="small" v-model="xmbzNo" class="w-200" placeholder="后台单号查询终点" clearable @keyup.enter.native="handleOrderSearch"></el-input>
          <el-button class="fr" size="small" @click="handleOrderSearch">查询</el-button>
        </div>
        <div>
          <el-input v-model="start.address" placeholder="起点" class="w-300" @focus="onSearchFocus({ type: 'start' })"
            @input="SearchAddress({ inputType: 'start', keyword: start.address })" clearable>
            <el-button slot="append" class="el-icon-map-location" @click="location('start')" title="定位"></el-button>
          </el-input>
        </div>
        <div>
          <el-input v-model="end.address" placeholder="终点" class="w-300" @focus="onSearchFocus({ type: 'end' })"
            @input="SearchAddress({ inputType: 'start', keyword: end.address })" clearable>
            <el-button slot="append" class="el-icon-map-location" @click="location('end')" title="定位"></el-button>
          </el-input>
        </div>
        <div class="mt-5">
          <span class="mr-10"><span class="c-999">距离：</span>{{ this.distance / 1000 }} 公里</span>
          <span><span class="c-999">费用：</span>{{ this.cost || '-' }} 元</span>
        </div>

        <div class="search-box" v-show="addressListVisible">
          <div v-if="addressList && addressList.length" class="address-list" v-loading="loading">
            <div class="address-item" v-for="(item, index) in addressList" :key="index" @click="onAddressSelect(item)">
              <div class="el-icon-location-information address-name">
                <span class="">{{ item.name }}</span>
              </div>
              <div class="mt-5 c-999 fz-12"><span v-if="item.district">{{ item.district }}</span></div>
            </div>
          </div>
          <XmEmpty v-else width="80px"></XmEmpty>
        </div>
      </section>

      <XmMap ref="xmMap" style="width: 100%;height: 100%;" @loadedMap="handleLoadedMap"></XmMap>
    </div>

    <radioSelectDialog dialogWidth="300px" title="该位置作为" ref="radioSelectDialog" :options="locationTypeList"
      @confirm="handleLocationOnMap"></radioSelectDialog>
  </basic-container>
</template>

<script>
import Clickoutside from 'element-ui/src/utils/clickoutside'
import { inputTipThrottle } from '@/util/map'
import { getStore } from '@/util/store'
import { icons } from "@/const";
import radioSelectDialog from '@/components/dialog/radioSelectDialog.vue';
import { getWarehouseList, getWarehouseByType, deliveryFee } from "@/api/warehouse";
import { orderList } from '@/api/pending'
import { getWarehouseLabel } from '@/util/map'
import AMap from 'AMap'

import {
  getOptionTree,
} from "@/api/system/dict";

const typeLabelMap = {
  'start': '起点',
  'end': '终点',
}

const locationTypeList = [{ label: '起点', value: 'start' }, { label: '终点', value: 'end' }]

export default {
  directives: {
    Clickoutside
  },
  components: {
    radioSelectDialog
  },
  data() {
    const cityId = getStore({ name: 'areaId' })
    return {
      cityId,
      loading: false,
      locationTypeList,
      currentType: '',
      start: {
        address: '',
        longitude: '',
        latitude: '',
      },
      end: {
        address: '',
        longitude: '',
        latitude: '',
      },
      addressList: [],
      addressListVisible: false,
      cost: 0,
      distance: 0,
      checkOnMap: false,
      costRangeList: [],
      xmbzNo: ''
    };
  },
  methods: {
    onSearchFocus({ type }) {
      this.addressListVisible = true
      this.addressList = []
      this.currentType = type
      if (type === 'start') {
        this.SearchAddress({ keyword: this.start.address })
      } else if (type === 'end') {
        this.SearchAddress({ keyword: this.end.address })
      }
    },
    onSearchClickOutside() {
      this.addressListVisible = false
    },
    // 搜索地址
    SearchAddress({ keyword }) {
      if (keyword) {
        const cityName = this.$refs.citySelect.getSelectedLabel()
        this.loading = true
        inputTipThrottle({
          city: cityName,
          keyword
        }).then(res => {
          this.addressList = res.map(item => {
            return {
              ...item,
              lng: item.location && item.location.lng,
              lat: item.location && item.location.lat,
            }
          }).sort((a, b) => {
            return a.district.includes(cityName) && !b.district.includes(cityName) ? -1 : 0
          })
        }).finally(() => {
          this.loading = false
        })
      } else {
        this.addressList = []
      }
    },
    onAddressSelect(item) {
      this.addressListVisible = false
      if (this.currentType === 'start') {
        this.start.address = item.name
        this.start.longitude = item.lng
        this.start.latitude = item.lat
      } else if (this.currentType === 'end') {
        this.end.address = item.name
        this.end.longitude = item.lng
        this.end.latitude = item.lat
      }
      this.createMarker({
        type: this.currentType,
        position: [item.lng, item.lat],
        label: {content: item.name}
      })
      this.$refs.xmMap.setCenter([item.lng, item.lat])
    },
    // 地图初始完成回调
    handleLoadedMap() {
      this.$refs.xmMap.map.on('click', this.handleMapClick);
      this.initDrving()
    },
    handleMapClick(event) {
      this.currentLnglat = event.lnglat
      this.addressListVisible = false
      if (this.checkOnMap) {
        this.$refs.radioSelectDialog.show()
        const defaultSelect = this.startMarker && !this.endMarker ? locationTypeList[1].value : locationTypeList[0].value
        this.$refs.radioSelectDialog.setSelected(defaultSelect)
      }
    },
    // 地图选址
    handleLocationOnMap(type) {
      if (this[type]) {
        this[type].address = `${typeLabelMap[type]}（${this.currentLnglat.lng},${this.currentLnglat.lat}）`
        this[type].longitude = this.currentLnglat.lng
        this[type].latitude = this.currentLnglat.lat
        this.createMarker({
          type,
          label: {content: this[type].address},
          position: [this.currentLnglat.lng, this.currentLnglat.lat]
        })
      }
    },
    // 创建起始点
    createMarker({ type, position, label }) {
      const map = this.$refs.xmMap.map
      const marker = new AMap.Marker({
        position: position,
        icon: icons[type === 'start' ? 'marker-start' : 'marker-end'],
        label: {
          direction: "top", //设置文本标注方位
          ...label
        },
        map: map
      })
      if (type === 'start') {
        this.startMarker && map.remove(this.startMarker)
        this.startMarker = marker
      } else if (type === 'end') {
        this.endMarker && map.remove(this.endMarker)
        this.endMarker = marker
      }
    },
    // 估算费用
    handleCost() {
      this.clearRouteData()
      if (!this.start.longitude || !this.start.address) {
        this.$message({ type: 'error', message: '请输入并选择起点！' })
        return
      }
      if (!this.end.longitude || !this.end.address) {
        this.$message({ type: 'error', message: '请输入并选择终点！' })
        return
      }
      this.driving.search(new AMap.LngLat(this.start.longitude, this.start.latitude), new AMap.LngLat(this.end.longitude, this.end.latitude), (status, result) => {
        if (status === 'complete') {
          if (result.routes && result.routes.length) {
            // 绘制第一条路线，也可以按需求绘制其它几条路线
            const first = result.routes[0]
            this.drawRoute(first)
            this.distance = first.distance
            this.cost = this.getCostByDistance(first.distance)
          }
        } else {
          this.$message({ type: 'error', message: '当前地址获取路径失败，请重试！' })
        }
      })
    },
    // 获取费用
    getCostByDistance(distance) {
      let cost = 100
      const item = this.costRangeList.find(item => {
        return distance / 1000 > item.min && distance / 1000 <= item.max
      })
      if (item) {
        cost = item.dictKey
      }
      return cost
    },
    clearRouteData() {
      this.routeMarker && this.$refs.xmMap.map.remove(this.routeMarker)
      this.routeMarker = null
      if (!this.start.address) {
        this.startMarker && this.$refs.xmMap.map.remove(this.startMarker)
        this.startMarker = null
      }
      if (!this.end.address) {
        this.endMarker && this.$refs.xmMap.map.remove(this.endMarker)
        this.endMarker = null
      }
      this.cost = 0
      this.distance = 0
    },
    // 绘制路径
    drawRoute(route) {
      const path = this.parseRouteToPath(route)
      const map = this.$refs.xmMap.map

      this.routeMarker = new AMap.Polyline({
        path: path,
        isOutline: true,
        outlineColor: '#ffeeee',
        borderWeight: 2,
        strokeWeight: 5,
        strokeOpacity: 0.9,
        strokeColor: '#0091ff',
        lineJoin: 'round'
      })

      map.add(this.routeMarker);

      // 调整视野达到最佳显示区域
      map.setFitView([this.routeMarker])
    },
    // 解析路径
    parseRouteToPath(route) {
      const path = []
      for (let i = 0, l = route.steps.length; i < l; i++) {
        const step = route.steps[i]
        for (let j = 0, n = step.path.length; j < n; j++) {
          path.push(step.path[j])
        }
      }
      return path
    },
    initDrving() {
      const drivingOption = {
        policy: AMap.DrivingPolicy.LEAST_DISTANCE,
      }
      this.driving = new AMap.Driving(drivingOption)
    },
    // 获取费用区间
    getOptionTree() {
      getOptionTree({ code: 'delivery_fee' }).then(res => {
        this.costRangeList = (res.data.data || []).map(item => {
          return {
            ...item,
            min: Number(item.dictValue.split('-')[0]),
            max: Number(item.dictValue.split('-')[1]),
          }
        })
      })
    },
    // 切换城市
    handleCityChange(cityId) {
      this.setWarehouseByCity(cityId)
      if (cityId) {
        this.setCenterByCity()
      }
      return
    },
    // 根据城市居中
    async setCenterByCity() {
      const cityName = this.$refs.citySelect.getSelectedLabel()
      if (!this.districtSearch) {
        this.districtSearch = await this.$refs.xmMap.districtSearchPlugin()
      }
      await new Promise((resolve) => {
        this.districtSearch.search(cityName, (status, result) => {
          const { lng, lat } = result.districtList[0] && result.districtList[0].center
          this.$refs.xmMap.setCenter([lng, lat])
          resolve()
        })
      })
    },
    // 绘制城市仓库范围
    setWarehouseByCity(cityId) {
      this.clearWarehoseMarkers()
      if (cityId) {
        this.addWarehouseOnMap(cityId)
        this.addPlatformWareOnMap(cityId)
      }
    },
    // 添加仓库范围
    addWarehouseOnMap(cityId) {
      return getWarehouseList({ cityId }).then(res => {
        const resData = res.data.data || [];
        if (resData && resData.length) {
          const markers = resData.map(item => {
            return this.$refs.xmMap.createMarker({
              longitude: item.longitude,
              latitude: item.latitude,
              label: {
                content: getWarehouseLabel(item)
              },
            })
          });

          const polygonPath = resData.map(item => {
            return item.geoJson.geometry.coordinates[0]
          })
          const polygon = this.$refs.xmMap.createPolygon({
            path: polygonPath,
            strokeColor: "#000",
            strokeWeight: 3,
            strokeOpacity: 1,
            fillOpacity: 0.4,
            fillColor: "#fff",
          });
          this.warehouseMarkers = [...markers, polygon]
          polygon.on('click', this.handleMapClick)
          this.$refs.xmMap.map.add(this.warehouseMarkers)
        }
      })
    },
    // 添加平台仓区域
    addPlatformWareOnMap(cityId) {
      getWarehouseByType({
        cityId,
        type: 99,// 平台仓
      }).then(res => {
        const resData = res.data.data || []
        if (resData && resData.length) {
          const markers = resData.map(item => {
            return this.$refs.xmMap.createMarker({
              longitude: item.longitude,
              latitude: item.latitude,
              label: {
                content: getWarehouseLabel(item)
              },
            })
          });

          const polygonPath = resData.map(item => {
            return item.geoJson.geometry.coordinates[0]
          })
          const polygon = this.$refs.xmMap.createPolygon({
            path: polygonPath,
            strokeColor: "#FF33FF",
            strokeWeight: 2,
            strokeOpacity: 1,
            fillOpacity: 0.4,
            fillColor: "#1791fc",
            zIndex: 20
          });
          polygon.on('click', this.handleMapClick)
          this.platformWareMarkers = [...markers, polygon]
          this.$refs.xmMap.map.add(this.platformWareMarkers)
        }
      })
    },
    clearWarehoseMarkers() {
      this.warehouseMarkers && this.$refs.xmMap.map.remove(this.warehouseMarkers)
      this.platformWareMarkers && this.$refs.xmMap.map.remove(this.platformWareMarkers)
    },
    // 加载完城市列表
    handleLoadedCityList() {
      if (this.$refs.xmMap && this.$refs.xmMap.map) {
        this.addWarehouseOnMap(this.cityId).then(() => {
          this.$refs.xmMap.setCenterByOverlays()
        })
        this.addPlatformWareOnMap(this.cityId)
      }
    },
    // 订单号查询
    handleOrderSearch() {
      if (!this.xmbzNo) {
        this.$message({ type: 'info', message: '请输入后台单号' })
        return
      }
      const params = {
        xmbzNo: this.xmbzNo,
      }
      deliveryFee(params).then(res => {
        const data = res.data.data && res.data.data[0]
        if (data) {
          this.end = {
            address: data.receiverAddress,
            longitude: data.receiverLongitude,
            latitude: data.receiverLatitude,
          }
          this.createMarker({
            type: 'end',
            position: [this.end.longitude, this.end.latitude],
            label: {content: this.end.address},
          })
          this.$refs.xmMap.setCenter([this.end.longitude, this.end.latitude])
        } else {
          this.$message({ type: 'error', message: '找不到该订单信息，请检查单号是否有误！' })
        }
      })
      const orderParams = {
        xmbzNo: this.xmbzNo,
        orderTimeSort: 0, // 下单时间排序
        deliveryTimeSort: 0, // 配送时间排序
      }
      orderList(orderParams).then(res => {
        const data = res.data.data && res.data.data.rows && res.data.data.rows[0]
        if (data) {
          this.cityId = data.deptId;
          this.setWarehouseByCity(this.cityId)
        }
      })
    },
    // 定位
    location(type) {
      if (this[type] && this[type].address && this[type].longitude && this[type].latitude) {
        this.$refs.xmMap.setCenter([this[type].longitude, this[type].latitude])
      }
    }
  },
  created() {
    this.getOptionTree()
  }
};
</script>
<style lang="scss" scoped>
.cost-calculation {
  .map-box {
    position: relative;
    width: 100%;
    height: 800px;

    .address-box {
      position: absolute;
      top: 20px;
      left: 20px;
      background: #fff;
      padding: 20px;
      z-index: 55;
      box-shadow: 2px 2px 2px rgba(0, 0, 0, .25);
      border-radius: 3px;

      .search-box {
        box-shadow: 2px 2px 2px rgba(0, 0, 0, .25);
        margin-top: 10px;
        max-height: 300px;
        overflow: auto;
        position: absolute;
        min-width: 100%;
        left: 0px;
        background-color: #fff;

        .address-list {
          cursor: pointer;

          .address-item {
            padding: 5px 10px;
            margin-top: 5px;

            .address-name {
              color: #333;
              font-weight: 700;
              font-size: 15px;
            }

            &:hover {
              background-color: #f4f4f4;
            }
          }
        }
      }
    }
  }
}</style>